﻿using MyHome.Configuration.Net;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using ViewModelBase;

namespace MyHome.Configuration.ViewModel
{
    public class PluginViewModel : ViewModelBase.ViewModel<PluginTemplate>
    {
        private IService client;
        private PluginHostViewModel host;

        public PluginViewModel(PluginTemplate model, PluginHostViewModel host)
            : base(model)
        {
            this.client = host.Model;
            this.host = host;
            Configuration = new ObservableCollection<DictionaryEntryViewModel<string, string>>(model.Configuration.Select(pair => new DictionaryEntryViewModel<string, string>(pair, model.Configuration)));
            Configuration.CollectionChanged += Configuration_CollectionChanged;
        }

        void Configuration_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
                foreach (DictionaryEntryViewModel<string, string> item in e.NewItems)
                {
                    Model.Configuration.Add(item.Key, item.Value);
                }

            if (e.OldItems != null)
                foreach (DictionaryEntryViewModel<string, string> item in e.OldItems)
                {
                    Model.Configuration.Remove(item.Key);
                }
        }

        #region ConnectWithInputPluginCommand

        private ICommand connectWithInputPluginCommand;

        public ICommand ConnectWithInputPluginCommand
        {
            get
            {
                if (connectWithInputPluginCommand == null)
                    connectWithInputPluginCommand = new RelayCommand(async param => await ExecuteConnectWithOhterPluginCommand(param));

                return connectWithInputPluginCommand;
            }
        }

        private async Task ExecuteConnectWithOhterPluginCommand(object param)
        {
            var input = param as PluginViewModel;
            if (input == null)
                return;

            // prevent double connections
            if (host.PluginConnections.Any(c => c.Input == input && c.Output == this))
                return;

            var connectionTemplate = new PluginConnectionTemplate { InputId = input.Id, OutputId = Id };
            var connection = new PluginConnectionViewModel(connectionTemplate, host);
            host.PluginConnections.Add(connection);
        }

        #endregion ConnectWithInputPluginCommand


        #region DeleteCommand

        private ICommand deleteCommand;

        public ICommand DeleteCommand
        {
            get
            {
                if (deleteCommand == null)
                    deleteCommand = new RelayCommand(async param => await ExecuteDeleteCommand(param));

                return deleteCommand;
            }
        }

        private async Task ExecuteDeleteCommand(object param)
        {
            var result = MessageBox.Show("Are you sure?", "", MessageBoxButton.YesNo, MessageBoxImage.Question);
            if (result == MessageBoxResult.Yes)
            {
                host.Plugins.Remove(this);
                host.SelectedPluginConnection = null;
            }
        }

        #endregion DeleteCommand
    
        
        public int Id
        {
            get { return Model.Id; }
        }

        public int X
        {
            get { return Model.X; }
            set
            {
                if (value != X)
                {
                    Model.X = value;
                    OnPropertyChanged("X");
                }
            }
        }

        public int Y
        {
            get { return Model.Y; }
            set
            {
                if (value != Y)
                {
                    Model.Y = value;
                    OnPropertyChanged("Y");
                }
            }
        }

        #region Selected property

        private bool isSelected;

        public bool IsSelected
        {
            get
            {
                return isSelected;
            }
            set
            {
                if (IsSelected != value)
                {
                    isSelected = value;
                    OnPropertyChanged("IsSelected");
                }
            }
        }

        #endregion Selected property

        #region Configuration property

        private ObservableCollection<DictionaryEntryViewModel<string, string>> configuration;

        public ObservableCollection<DictionaryEntryViewModel<string, string>> Configuration
        {
            get
            {
                return configuration;
            }
            set
            {
                if (Configuration != value)
                {
                    configuration = value;
                    OnPropertyChanged("Configuration");
                }
            }
        }

        #endregion Configuration property

        #region AddConfigurationEntryCommand

        private ICommand addConfigurationEntryCommand;

        public ICommand AddConfigurationEntryCommand
        {
            get
            {
                if (addConfigurationEntryCommand == null)
                    addConfigurationEntryCommand = new RelayCommand(async param => await ExecuteAddConfigurationEntryCommand(param));

                return addConfigurationEntryCommand;
            }
        }

        private async Task ExecuteAddConfigurationEntryCommand(object param)
        {
            Configuration.Add(new DictionaryEntryViewModel<string, string>(new KeyValuePair<string, string>("", ""), Model.Configuration));
        }

        #endregion AddConfigurationEntryCommand
    

        public string PluginType
        {
            get { return Model.PluginType; }
        }

        public string Type
        {
            get { return Model.Type; }
        }

        public string Namespace
        {
            get { return Type.Substring(0, Type.LastIndexOf('.')); }
        }

        public string ClassName
        {
            get { return Type.Substring(Type.LastIndexOf('.') + 1, Type.Length - Type.LastIndexOf('.') - 1); }
        }

        public bool IsInputPlugin
        {
            get { return PluginType == "Input" || PluginType == "InputOutput" || PluginType == "Processing"; }
        }

        public bool IsNotInputPlugin
        {
            get { return !IsInputPlugin; }
        }

        public bool IsOutputPlugin
        {
            get { return PluginType == "Output" || PluginType == "InputOutput" || PluginType == "Processing"; }
        }

        public bool IsNotOutputPlugin
        {
            get { return !IsOutputPlugin; }
        }

        public override string ToString()
        {
            return string.Format("{{{0} Id: {1}}}", PluginType, Id);
        }
    }
}